package cn.numeron.common.utility

import android.content.Context
import android.content.pm.PackageManager
import cn.numeron.android.AppRuntime
import cn.numeron.common.extension.GsonHelper
import cn.numeron.common.extension.format
import cn.numeron.okhttp.*
import cn.numeron.retrofit.DateConverterFactory
import cn.numeron.retrofit.FileConverterFactory
import coil.util.CoilUtils
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import okhttp3.Dispatcher
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.*
import java.util.concurrent.TimeUnit

@Module
@InstallIn(SingletonComponent::class)
object Http {

    lateinit var baseUrl: String
        private set

    fun init(context: Context) {
        baseUrl = context.packageManager
            .getApplicationInfo(context.packageName, PackageManager.GET_META_DATA)
            .metaData
            .getString("base_url")
            ?: throw IllegalArgumentException("Please put base_url to meta-data.")
    }

    @get:Provides
    val okHttpClient: OkHttpClient by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        OkHttpClient.Builder()
            .readTimeout(16, TimeUnit.SECONDS)
            .writeTimeout(16, TimeUnit.SECONDS)
            .connectTimeout(8, TimeUnit.SECONDS)
            .cache(CoilUtils.createDefaultCache(AppRuntime.context))
            .addInterceptor(RetryInterceptor())
            .addInterceptor(ProgressInterceptor())
            .addInterceptor(OAuthClientInterceptor(HeadersManager))
            .addInterceptor(TextLogInterceptor(Logger).setLevel(LogLevel.BODY))
            .build()
    }

    @get:Provides
    val retrofit by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .callbackExecutor(okHttpClient.dispatcher.executorService)
            .addConverterFactory(FileConverterFactory())
            .addConverterFactory(DateConverterFactory.create(Date::format))
            .addConverterFactory(GsonConverterFactory.create(GsonHelper.gson))
            .build()
    }

}